

AnimationStatus = {

    AnimationStart:"animationstart",
    AnimationCancel:"animationcancel",
    AnimationEnd:"animationend",
    AnimationIteration:"animationiteration",
}
CubeBezierType={

    Linner:0,
    Easy:1,
    EasyOut:2,
    EasyIn:3,
    EasyInOut:4,
    Power2:5,
    Power5:6,
    Arc:7,
    Bow:8,
    Bounce:9,
    Elastic:10
}

class StoryPanel {

    constructor(dom){

        this.Sequences={list:[],start:null};//动画序列
        this.playseq = false;
        this.animindex = 0; //当前动画下标
        this.dom = dom;
        this.count = 0;
        this.Symps = [];
    }

    createAnimate({timing, draw, duration, type,symp}) {

         let that = this;
         let start = performance.now();
         requestAnimationFrame(function animate(time) {
            // timeFraction goes from 0 to
            let timeFraction = (time - start) / duration;
            if (timeFraction > 1) timeFraction = 1;

            // calculate the current animation state
            let progress = timing(timeFraction,type,that,symp)

            draw(progress); // draw it

            if (timeFraction < 1) {
                requestAnimationFrame(animate);
            }
        });
    }


    createCustiomAnimate({draw, duration,type}) {

        let that = this;
        let symp = Symbol();
        let func = ()=> {
            let start = performance.now();
            requestAnimationFrame(function animate(time) {
                let timeFraction = (time - start) / duration;
                if (timeFraction > 1) timeFraction = 1;

                let progress = that.normalTiming(timeFraction,type,that,symp)

                draw(progress);

                if (timeFraction < 1) {
                    requestAnimationFrame(animate);
                }
            });
        }
        return {start:func,symp:symp,time:duration}
    }

    moveBy(pos,time,type){

        let symp = Symbol();
        let func = ()=> {
            let currentpos =  {x:this.dom.offsetLeft, y:this.dom.offsetTop};
            let offset = {x:pos.x,y:pos.y};
            this.createAnimate({
                timing: this.normalTiming, draw: (progress) => {
                    this.dom.style.left = currentpos.x + progress * offset.x + "px";
                    this.dom.style.top = currentpos.y + progress * offset.y + "px";
                }, duration: time,type:type,symp:symp
            });
        }

        return {start:func,symp:symp,time:time};
    }

    moveTo(pos,time,type){

        let symp = Symbol();
        let func = ()=> {

            let curpos = {x: this.dom.offsetLeft, y: this.dom.offsetTop};
            let offset = this.getPosOffset(pos,curpos);
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
                this.dom.style.left = curpos + offset * progress + "px";
                this.dom.style.top  = curpos + offset * progress + "px";
            },duration:time,type:type,symp:symp});
        }
        return {start:func,symp:symp,time:time};
    }

    sizeTo(size,time,type){

       let symp = Symbol();
       let func = ()=> {
           let cursize = {x:this.dom.offsetWidth, y:this.dom.offsetHeight};
           let offset = this.getSizeOffset(size,cursize);
           this.createAnimate({timing:this.normalTiming, draw: (progress) => {
                   this.dom.style.width = cursize.x + progress * offset.x + "px";
                   this.dom.style.height = cursize.y + progress * offset.y + "px";
               }, duration: time,type:type,symp:symp
           });
       }
       return {start:func,symp:symp,time:time};
    }
    scaleTo(scale,time,type){

        let symp =  Symbol();
        let func = ()=> {
            let curscale = this.getTransformScale();
            let offset = this.getScaleOffset(scale,curscale);
            let angstr = this.getStyleByName("transform");
            let angle = this.getTransformAngleFromStr(angstr);
            this.createAnimate({
                timing: this.normalTiming, draw: (progress) => {
                    this.dom.style.transform = "rotate("+ angle +"deg) scale(" + (curscale.x + progress * offset.x) + ")";
                }, duration: time,type:type,symp:symp
            });
        }
        return {start:func,symp:symp,time:time};
    }

    scaleBy(scale,time,type){

        let symp = Symbol();
        let func = ()=>{
            let curscale = this.getTransformScale();
            let offset = {x:scale.x,y:scale.y};
            let angstr = this.getStyleByName("transform");
            let angle  = this.getTransformAngleFromStr(angstr);
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
               this.dom.style.transform = "rotate("+ angle +"deg) scale(" + (curscale.x + progress * offset.x) + ")";
            },duration:time,type:type,symp:symp});
        }
        return {start:func,symp:symp,time:time};
    }
    //旋转
    rotateTo(angle,time,type){

        let symp = Symbol();
        let func = ()=>{
            let currotate = this.getStyleByName("transform");
            let ang = this.getTransformAngleFromStr(currotate);
            let scale = this.getTransformScale();
            let offset = this.getAngleOffset(angle,ang);
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
                this.dom.style.transform = "rotate(" + (ang + progress *offset) +"deg)" + "scale(" + scale.x+","+scale.y+")";
            },duration:time,type:type,symp:symp})
        }
        return {start:func,symp:symp,time:time}
    }

    rotateBy(angle,time,type){

        let symp = Symbol();
        let func = ()=>{
            let currotate = this.getStyleByName("transform");
            let ang = this.getTransformAngleFromStr(currotate);
            let scale = this.getTransformScale();
            let offset = ang;
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
                this.dom.style.transform = "rotate(" + (ang + progress *offset) +"deg)" + "scale(" + scale.x+","+scale.y+")";
            },duration:time,type:type,symp:symp})

        }
        return {start:func,symp:symp,time:time};
    }

    //透明渐变
    fadeOpacity(opacity,time,type){
        let symp =  Symbol();
        let func = ()=>{

            let opc = parseFloat(this.getStyleByName("opacity"));
            let offset = opacity - opc;
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
                this.dom.style.opacity = opc + progress * offset +"";

            },duration:time,type:type,symp:symp})
        }
        return {start:func,symp:symp,time:time};
    }

   //颜色渐变
    fadeBgColor(color,time,type){

        let symp = Symbol();
        let func = ()=> {
            //暂时这样处理
            let colorstr = this.getStyleByName("background-color");
            let curcolor = this.getColorFromStr(colorstr);
            let offset = this.getColorOffset(color,curcolor);
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
                this.dom.style.backgroundColor = "rgba(" + (curcolor.r + offset.r * progress) + ","+(curcolor.g + offset.g * progress )+","
                +(curcolor.b + offset.b * progress) +","+(curcolor.a + offset.a * progress) +")";

            },duration:time,type:type,symp:symp});
        }
        return {start:func,symp:symp,time:time};
    }

    fadeFontColor(color,time,type){

        let symp =  Symbol();
        let func = ()=> {
            //暂时这样处理
            let colorstr = this.getStyleByName("color");
            let curcolor = this.getColorFromStr(colorstr);
            let offset = this.getColorOffset(color,curcolor);
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
                    this.dom.style.color = "rgba(" + (curcolor.r + offset.r * progress) + ","+(curcolor.g + offset.g * progress )+","
                        +(curcolor.b + offset.b * progress) +","+(curcolor.a + offset.a * progress) +")";

                },duration:time,type:type,symp:symp});
        }
        return {start:func,symp:symp,time:time};
    }


   //融合动画
    createFusion(){

        let symp = Symbol();
        if(arguments.length<=0){
            console.error("NO Arguments!!!");
            return {start:null,symp:symp,time:-1}
        }
        let maxtime = arguments[0].time;
        for(let i=1;i<arguments.length;i++){
            if(arguments[i].time>maxtime){
                maxtime = arguments[i].time;
            }
        }
        let func = ()=>{

            for(let i=0;i<arguments.length;i++){
                arguments[i].start();
            }
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{

            },duration:maxtime,type:CubeBezierType.Linner,symp:symp});
        }
        return {start:func,symp:symp,time:maxtime};
    }

    //延时
    delayTime(time){

        let symp =  Symbol();
        let func = ()=>{

            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{
                // do nothing
             },duration:time,type:CubeBezierType.Linner,symp:symp});
        }
        return {start:func,symp:symp,time:time};
    }

    //回调动画
    callBackFunc(callback){
        let symp =  Symbol();
        let func=()=>{
            this.createAnimate({timing:this.normalTiming,draw:(progress)=>{

                callback();
            },duration:0.01,type:CubeBezierType.Linner,symp:symp});

        }
        return {start:func,symp:symp,time:0.01};
    }

    //对时间不做处理
    normalTiming(timeFraction,type,that,symp){

        if(that.playseq==true&&that.Symps.indexOf(symp)>=0){
            //当前动画执行完毕了
            if(timeFraction>=1){
                that.animindex++;
                that.PlayAnimationByIndex(that.animindex);
            }
        }

        let time =0;
        switch (type) {

          case CubeBezierType.Linner:
                time = timeFraction;
                break;
          case CubeBezierType.Power2:
                time = Math.pow(timeFraction,2);
                 break;
            case CubeBezierType.Power5:
                time = Math.pow(timeFraction,5);
                 break;
            case CubeBezierType.Arc:
                time = 1 - Math.sin(Math.acos(timeFraction));
                break;
            case CubeBezierType.Bow:
                time = Math.pow(timeFraction,2) * ((1 + 1) * timeFraction - 1);
                break;
            case CubeBezierType.Bounce:
                 for(let a = 0,b=1,result;1;a+=b,b/=2){
                     if(timeFraction>=(7 - 4 * a)/11)
                     {
                         time = Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2);
                     }
                 }
                 break;
            case CubeBezierType.Elastic:
                time = Math.pow(2,10 * (timeFraction - 1)) * Math.cos(20 * Math.PI *  1.5 / 3 * timeFraction);

          default:
              time = timeFraction;
                break;
        }

        return time;
    }

    //把动画加入到序列
    createSequences(){
        for(let i = 0;i<arguments.length;i++){
            this.Sequences.list.push(arguments[i]);
            this.Symps.push(arguments[i].symp)
            this.count++;
        }
    }

    //从动画序列中执行动画
    startAnimtionFormSequences(){

        this.playseq = true;
        this.animindex = 0;
        this.Sequences.list[0].start();

    }

    PlayAnimationByIndex(index){

      if(index<this.Sequences.list.length) {
          this.Sequences.list[index].start();
      }
    }


    getStyleByName(name){

       return window.getComputedStyle(this.dom,"").getPropertyValue(name);
    }

    //从属性字符串中抽取rgba值
    getColorFromStr(colorstr){

        if(colorstr.split("(")[0].length>3){

            let content = colorstr.slice(5,colorstr.length-1)
            content = content.replace(/\s+/g,"")
            let color = content.split(",");
            return {r: parseInt(color[0]),g:parseInt(color[1]),b:parseInt(color[2]),a:parseFloat(color[3])};

        }else{

            let content = colorstr.slice(4,colorstr.length-1)
            content = content.replace(/\s+/g,"")
            let color = content.split(",");
            return {r: parseInt(color[0]),g:parseInt(color[1]),b:parseInt(color[2]),a:1};
        }
    }

    clearSequence(){

        this.Sequences={list:[],start:null};//动画序列
        this.playseq = false;
        this.animindex = 0; //当前动画下标
        this.count = 0;
        this.Symps = [];
    }

    //从属性字符串中抽取Transform 各属性
    getTransformAngleFromStr(anglestr){

        if(anglestr==null||anglestr=="none"){

            return 0;
        }
        let values = anglestr.split('(')[1].split(')')[0].split(',');
        let a = values[0];
        let b = values[1];
        let c = values[2];
        let d = values[3];
        let scale = Math.sqrt(a * a + b * b);
        console.log("he"+Math.sqrt(b*b + c*c));
        let sin = b / scale;
        return Math.round(Math.atan2(b,a) * (180 / Math.PI));
    }

    getTransformScale(){

        return {x:this.dom.getBoundingClientRect().width/this.dom.offsetWidth,y:this.dom.getBoundingClientRect().height/this.dom.offsetHeight};
    }

    //获取颜色插值
    getColorOffset(color1,color2){


        return {r:color1.r-color2.r,g:color1.g-color2.g,b:color1.b-color2.b,a:color1.a-color2.a};
    }
    //获取角度插值
    getAngleOffset(angle1,angle2){
        return angle1 - angle2;
    }
    //获取放大的插值
    getScaleOffset(scale1,scale2){
        return {x:scale1.x-scale2.x,y:scale1.y-scale2.y};
    }
    //获取size的插值
    getSizeOffset(size1,size2){

        return {x:size1.x - size2.x,y:size1.y - size2.y}
    }
    getPosOffset(pos1,pos2){
        return {x:pos1.x - pos2.x,y:pos1.y - pos2.y};
    }

}




